// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the CELESTIALBODY_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// CELESTIALBODY_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef CELESTIALBODY_EXPORTS
#define CELESTIALBODY_API __declspec(dllexport)
#else
#define CELESTIALBODY_API __declspec(dllimport)
#endif

// This class is exported from the CelestialBody.dll
class CELESTIALBODY_API CCelestialBody {
public:
	CCelestialBody(void);
	// TODO: add your methods here.
};

extern CELESTIALBODY_API int nCelestialBody;

CELESTIALBODY_API int fnCelestialBody(void);

#define CELESTIAL_BODY_SLICES 20
#define CELESTIAL_BODY_STACKS 20

#pragma once

#include <gl\glew.h>
#include <gl\freeglut.h>
#include "..\Geometry\Geometry.h"
#include <vector>

class CELESTIALBODY_API CelestialBody
{
private:
	VectorMath::Vector3 offsetFromParent;
	double rotationYAroundParent_degs;
	double radius;
	double angularVelocity_degsPerFrame;

	float colorRed, colorGreen, colorBlue;

	CelestialBody * parent;
	std::vector <CelestialBody *> satellites;
public:
	CelestialBody ()
	{
		this->rotationYAroundParent_degs = 0;
		this->angularVelocity_degsPerFrame = 0;
		this->offsetFromParent = VectorMath::Vector3();
		this->radius = 0;
		this->colorRed = 0;
		this->colorGreen = 0;
		this->colorBlue = 0;

		this->parent = NULL;
		this->satellites.resize(0);
	}

	CelestialBody (VectorMath::Vector3 offsetFromParent, double rotationYAroundParent, double radius,
		double angularVelocity_degsPerFrame,
		float colorRed, float colorGreen, float colorBlue,
		CelestialBody * parent = NULL)
	{
		this->offsetFromParent = offsetFromParent;
		this->rotationYAroundParent_degs = rotationYAroundParent;
		this->radius = radius;
		this->angularVelocity_degsPerFrame = angularVelocity_degsPerFrame;
		this->colorRed = colorRed;
		this->colorGreen = colorGreen;
		this->colorBlue = colorBlue;
		this->parent = parent;
	}

	CelestialBody (double radius,
		double angularVelocity_degsPerFrame,
		float colorRed, float colorGreen, float colorBlue,
		CelestialBody * parent = NULL)
	{
		this->offsetFromParent = VectorMath::Vector3();
		this->rotationYAroundParent_degs = 0;
		this->radius = radius;
		this->angularVelocity_degsPerFrame = angularVelocity_degsPerFrame;
		this->colorRed = colorRed;
		this->colorGreen = colorGreen;
		this->colorBlue = colorBlue;
		this->parent = parent;
	}

	void AddSatellite (CelestialBody * satellite)
	{
		this->satellites.push_back (satellite);
		satellite->parent = this;
	}

	void AddSatellite (CelestialBody * satellite, VectorMath::Vector3 offsetFromParent = VectorMath::Vector3())
	{
		this->satellites.push_back (satellite);
		satellite->parent = this;
		satellite->offsetFromParent = offsetFromParent;
	}

	void static Update (CelestialBody *bodyToUpdate)
	{
		if(bodyToUpdate->parent != NULL)
		{
			bodyToUpdate->rotationYAroundParent_degs += bodyToUpdate->angularVelocity_degsPerFrame;
		}

		int satellitesNum = bodyToUpdate->satellites.size();
		for(int i=0; i < satellitesNum; i++)
		{
			CelestialBody::Update(bodyToUpdate->satellites[i]);
		}
	}

	void static Render (CelestialBody *body)
	{
		glPushMatrix();

		glRotatef (body->rotationYAroundParent_degs, 0, 1.0, 0);
		glTranslatef (body->offsetFromParent.GetX(), body->offsetFromParent.GetY(), body->offsetFromParent.GetZ());
		glColor4f (body->colorRed, body->colorGreen, body->colorBlue, 1.0);
		glutSolidSphere (body->radius, CELESTIAL_BODY_SLICES, CELESTIAL_BODY_STACKS);
		
		glPushMatrix();
		
		glPopMatrix();
		
		int satellitesNum = body->satellites.size();
		for(int i=0; i < satellitesNum; i++)
		{
			CelestialBody::Render(body->satellites[i]);
		}
		

		glPopMatrix();
	}
};